Sparkling plot
Javascript cells
Example with sparkles plot
He we will couple Javascript canvas and WL plot function
Download original notebook.js const canvas = document.createElement('canvas'); canvas.width = 600; canvas.height = 400; const context = canvas.getContext('2d'); const particles = []; function random (min, max) { return Math.random() * (max - min) + min; } function convertRange( value, r1, r2 ) { return ( value - r1[ 0 ] ) * ( r2[ 1 ] - r2[ 0 ] ) / ( r1[ 1 ] - r1[ 0 ] ) + r2[ 0 ]; } let uid = 0; let data = []; function animate() { if (data.length > 0) { for (let j=0; j<3; ++j) { const it = Math.floor(random(0, data.length-1)); const particle = { x: data[it][0], y: data[it][1], xvel: random(-1,1), yvel: random(-1,1), color: `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.5)`, size: 7, age: 1 }; particles.push(particle); if (particles.length > 2000) { particles.shift(); } } } context.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < particles.length; i += 1){ const p = particles[i]; context.beginPath(); context.arc(p.x, p.y, p.size/p.age, 0, Math.PI * 2, true); context.fillStyle = p.color; context.fill(); context.closePath(); p.age += 0.1; p.x += p.xvel; p.y -= p.yvel; } uid = window.requestAnimationFrame(animate); } this.ondestroy = () => { window.cancelAnimationFrame(uid) } //function definition core.Spark = async (args, env) => { //update the positions const raw = await interpretate(args[0], env); const min = [Math.min.apply(null, raw.map((e) => e[0])), Math.min.apply(null, raw.map((e) => e[1]))]; const max = [Math.max.apply(null, raw.map((e) => e[0])), Math.max.apply(null, raw.map((e) => e[1]))]; data = raw.map((e)=>[convertRange(e[0], [min[0], max[0]], [50, 550]), convertRange(e[1], [max[1], min[1]], [50, 350])]); } //kickstarter animate(); return canvas;
const canvas = document.createElement('canvas'); canvas.width = 600; canvas.height = 400; const context = canvas.getContext('2d'); const particles = []; function random (min, max) { return Math.random() * (max - min) + min; } function convertRange( value, r1, r2 ) { return ( value - r1[ 0 ] ) * ( r2[ 1 ] - r2[ 0 ] ) / ( r1[ 1 ] - r1[ 0 ] ) + r2[ 0 ]; } let uid = 0; let data = []; function animate() { if (data.length > 0) { for (let j=0; j<3; ++j) { const it = Math.floor(random(0, data.length-1)); const particle = { x: data[it][0], y: data[it][1], xvel: random(-1,1), yvel: random(-1,1), color: `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.5)`, size: 7, age: 1 }; particles.push(particle); if (particles.length > 2000) { particles.shift(); } } } context.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < particles.length; i += 1){ const p = particles[i]; context.beginPath(); context.arc(p.x, p.y, p.size/p.age, 0, Math.PI * 2, true); context.fillStyle = p.color; context.fill(); context.closePath(); p.age += 0.1; p.x += p.xvel; p.y -= p.yvel; } uid = window.requestAnimationFrame(animate); } this.ondestroy = () => { window.cancelAnimationFrame(uid) } //function definition core.Spark = async (args, env) => { //update the positions const raw = await interpretate(args[0], env); const min = [Math.min.apply(null, raw.map((e) => e[0])), Math.min.apply(null, raw.map((e) => e[1]))]; const max = [Math.max.apply(null, raw.map((e) => e[0])), Math.max.apply(null, raw.map((e) => e[1]))]; data = raw.map((e)=>[convertRange(e[0], [min[0], max[0]], [50, 550]), convertRange(e[1], [max[1], min[1]], [50, 350])]); } //kickstarter animate(); return canvas;
Now a couple of adapters to make it easier
SparkPlot[func_, range_] := With[{var = Extract[range,1, Inactivate], min = range[[2]], max = range[[3]]}, Table[{var, func}, {var, min, max, (max-min)/200.0}]] // FrontSubmit[Spark[#]] & SetAttributes[SparkPlot, HoldAll]
Click on any button down there
Button["Sinc", SparkPlot[Sinc[x], {x,-10,10}]] Button["Cos", SparkPlot[Cos[x], {x,-10,10}]] Button["x", SparkPlot[x, {x,-10,10}]]
(*VB[*)(EventObject[<|"Id" -> "d2a2f570-23bb-4f96-9a24-ac2c630aaa56", "Initial" -> False, "View" -> "67651fbd-9a8b-4f9e-b498-5f83cda30391"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKm5mbmRqmJaXoWiZaJOmapFmm6iaZWFromqZZGCenJBobGFsaAgCIeRW5"*)(*]VB*)
(*VB[*)(EventObject[<|"Id" -> "664aa2f9-546a-4cd5-941e-1da36df42bc1", "Initial" -> False, "View" -> "c030c8fd-1bcd-473e-a387-9f46a1e4d079"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJxsYGyRbpKXoGiYlp+iamBun6iYaW5jrWqaZmCUappqkGJhbAgCMnRXW"*)(*]VB*)
(*VB[*)(EventObject[<|"Id" -> "4b322b3f-48c9-4c96-9423-c8eeb55eddbd", "Initial" -> False, "View" -> "f63cf7fe-91c7-4b52-95cf-67a91de39074"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKp5kZJ6eZp6XqWhomm+uaJJka6VqaJqfpmpknWhqmpBpbGpibAACNyhW9"*)(*]VB*)